{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bk-root\">\n",
       "        <a href=\"https://bokeh.pydata.org\" target=\"_blank\" class=\"bk-logo bk-logo-small bk-logo-notebook\"></a>\n",
       "        <span id=\"4121000d-f4f9-4a63-8f6b-c8de71369b68\">Loading BokehJS ...</span>\n",
       "    </div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  var force = true;\n",
       "\n",
       "  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "  var JS_MIME_TYPE = 'application/javascript';\n",
       "  var HTML_MIME_TYPE = 'text/html';\n",
       "  var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  var CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    var script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    var cell = handle.cell;\n",
       "\n",
       "    var id = cell.output_area._bokeh_element_id;\n",
       "    var server_id = cell.output_area._bokeh_server_id;\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null && id in Bokeh.index) {\n",
       "      Bokeh.index[id].model.document.clear();\n",
       "      delete Bokeh.index[id];\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            var id = msg.content.text.trim();\n",
       "            if (id in Bokeh.index) {\n",
       "              Bokeh.index[id].model.document.clear();\n",
       "              delete Bokeh.index[id];\n",
       "            }\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    var output_area = handle.output_area;\n",
       "    var output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      var bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      var script_attrs = bk_div.children[0].attributes;\n",
       "      for (var i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      var toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    var events = require('base/js/events');\n",
       "    var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  \n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  var NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded() {\n",
       "    var el = document.getElementById(\"4121000d-f4f9-4a63-8f6b-c8de71369b68\");\n",
       "    if (el != null) {\n",
       "      el.textContent = \"BokehJS is loading...\";\n",
       "    }\n",
       "    if (root.Bokeh !== undefined) {\n",
       "      if (el != null) {\n",
       "        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(display_loaded, 100)\n",
       "    }\n",
       "  }\n",
       "\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n",
       "    }\n",
       "    finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.info(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(js_urls, callback) {\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = js_urls.length;\n",
       "    for (var i = 0; i < js_urls.length; i++) {\n",
       "      var url = js_urls[i];\n",
       "      var s = document.createElement('script');\n",
       "      s.src = url;\n",
       "      s.async = false;\n",
       "      s.onreadystatechange = s.onload = function() {\n",
       "        root._bokeh_is_loading--;\n",
       "        if (root._bokeh_is_loading === 0) {\n",
       "          console.log(\"Bokeh: all BokehJS libraries loaded\");\n",
       "          run_callbacks()\n",
       "        }\n",
       "      };\n",
       "      s.onerror = function() {\n",
       "        console.warn(\"failed to load library \" + url);\n",
       "      };\n",
       "      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "    }\n",
       "  };var element = document.getElementById(\"4121000d-f4f9-4a63-8f6b-c8de71369b68\");\n",
       "  if (element == null) {\n",
       "    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '4121000d-f4f9-4a63-8f6b-c8de71369b68' but no matching script tag was found. \")\n",
       "    return false;\n",
       "  }\n",
       "\n",
       "  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-0.13.0.min.js\"];\n",
       "\n",
       "  var inline_js = [\n",
       "    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "    \n",
       "    function(Bokeh) {\n",
       "      \n",
       "    },\n",
       "    function(Bokeh) {\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css\");\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    \n",
       "    if ((root.Bokeh !== undefined) || (force === true)) {\n",
       "      for (var i = 0; i < inline_js.length; i++) {\n",
       "        inline_js[i].call(root, root.Bokeh);\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      var cell = $(document.getElementById(\"4121000d-f4f9-4a63-8f6b-c8de71369b68\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(js_urls, function() {\n",
       "      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  var force = true;\n\n  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n  \n\n  \n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  var NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded() {\n    var el = document.getElementById(\"4121000d-f4f9-4a63-8f6b-c8de71369b68\");\n    if (el != null) {\n      el.textContent = \"BokehJS is loading...\";\n    }\n    if (root.Bokeh !== undefined) {\n      if (el != null) {\n        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(display_loaded, 100)\n    }\n  }\n\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n    }\n    finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.info(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(js_urls, callback) {\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = js_urls.length;\n    for (var i = 0; i < js_urls.length; i++) {\n      var url = js_urls[i];\n      var s = document.createElement('script');\n      s.src = url;\n      s.async = false;\n      s.onreadystatechange = s.onload = function() {\n        root._bokeh_is_loading--;\n        if (root._bokeh_is_loading === 0) {\n          console.log(\"Bokeh: all BokehJS libraries loaded\");\n          run_callbacks()\n        }\n      };\n      s.onerror = function() {\n        console.warn(\"failed to load library \" + url);\n      };\n      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.getElementsByTagName(\"head\")[0].appendChild(s);\n    }\n  };var element = document.getElementById(\"4121000d-f4f9-4a63-8f6b-c8de71369b68\");\n  if (element == null) {\n    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '4121000d-f4f9-4a63-8f6b-c8de71369b68' but no matching script tag was found. \")\n    return false;\n  }\n\n  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-0.13.0.min.js\"];\n\n  var inline_js = [\n    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\n    \n    function(Bokeh) {\n      \n    },\n    function(Bokeh) {\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css\");\n    }\n  ];\n\n  function run_inline_js() {\n    \n    if ((root.Bokeh !== undefined) || (force === true)) {\n      for (var i = 0; i < inline_js.length; i++) {\n        inline_js[i].call(root, root.Bokeh);\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      var cell = $(document.getElementById(\"4121000d-f4f9-4a63-8f6b-c8de71369b68\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(js_urls, function() {\n      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from scipy.stats import norm\n",
    "import matplotlib.pylab as plt\n",
    "import pandas as pd\n",
    "from bokeh.layouts import row, widgetbox, layout, gridplot\n",
    "from bokeh.models import CustomJS, Slider\n",
    "from bokeh.plotting import figure, output_file, show, ColumnDataSource\n",
    "from bokeh.models.glyphs import MultiLine\n",
    "from bokeh.io import output_notebook\n",
    "from bokeh.models.widgets import Div\n",
    "%matplotlib inline\n",
    "output_notebook()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "num_data = 10\n",
    "X = norm.rvs(size=(num_data,3), random_state=42)\n",
    "#X = np.dot(Y, np.linalg.cholesky([[1, 0.6], [0.6, 0.6]]))\n",
    "m = X.mean(axis=0)\n",
    "X = X - m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.2448435 ,  0.34463606,  0.98109952],\n",
       "       [ 1.2711592 ,  0.24874699,  0.09927402],\n",
       "       [ 1.32734216,  1.25033509, -0.13606341],\n",
       "       [ 0.29068939,  0.01948267, -0.13231877],\n",
       "       [-0.00990838, -1.43037988, -1.39150685],\n",
       "       [-0.81415818, -0.52993076,  0.64765831],\n",
       "       [-1.15989473, -0.92940334,  1.79905975],\n",
       "       [-0.47764695,  0.55042856, -1.09133721],\n",
       "       [-0.79625338,  0.59382295, -0.8175826 ],\n",
       "       [ 0.12382737, -0.11773833,  0.04171723]])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nH8cAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(111, projection='3d')\n",
    "\n",
    "ax.scatter(X[:,0], X[:,1], X[:,2])\n",
    "\n",
    "ax.set_xlabel('X Label')\n",
    "ax.set_ylabel('Y Label')\n",
    "ax.set_zlabel('Z Label')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "a, b = np.linalg.eig(np.cov(X.T));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.34832021, 1.139166  , 0.78744362])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.66121255, -0.57561026,  0.48111412],\n",
       "       [-0.74967543, -0.48303245,  0.45240071],\n",
       "       [ 0.02801275,  0.65981246,  0.75090798]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-0.57561026 -0.48303245  0.65981246]\n",
      " [-0.48111412 -0.45240071 -0.75090798]\n",
      " [ 0.66121255 -0.74967543  0.02801275]]\n",
      "[1.139166   0.78744362 0.34832021]\n"
     ]
    }
   ],
   "source": [
    "from sklearn.decomposition import PCA\n",
    "pca = PCA(n_components=3)\n",
    "pca.fit(X)\n",
    "print(pca.components_)  \n",
    "print(pca.explained_variance_) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X_star = pca.transform(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.33993686, -1.01042672, -0.06898829],\n",
       "       [-0.7863429 , -0.79865162,  0.65680785],\n",
       "       [-1.45776051, -1.10208444, -0.06350171],\n",
       "       [-0.26404013, -0.04930952,  0.17389518],\n",
       "       [-0.2215103 ,  1.69676554,  1.02678917],\n",
       "       [ 1.15194458,  0.14511225, -0.12291284],\n",
       "       [ 2.30362132, -0.37242386, -0.01978948],\n",
       "       [-0.71101426,  0.80028224, -0.75904029],\n",
       "       [-0.36795533,  0.72837212, -0.99456994],\n",
       "       [ 0.01312068, -0.03763599,  0.17131036]])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_star"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "# keep projections onto first two pcs\n",
    "F_2 = np.dot(pca.components_[0:2,:], X.T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.02524940e+01, -4.98606135e-15],\n",
       "       [-4.98606135e-15,  7.08699260e+00]])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(F_2, F_2.T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# keep projection onto first pc\n",
    "F_1 = np.dot(pca.components_[0,:], X.T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.33993686, -0.7863429 , -1.45776051, -0.26404013, -0.2215103 ,\n",
       "        1.15194458,  2.30362132, -0.71101426, -0.36795533,  0.01312068])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "F_1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.2448435 ,  0.34463606,  0.98109952],\n",
       "       [ 1.2711592 ,  0.24874699,  0.09927402],\n",
       "       [ 1.32734216,  1.25033509, -0.13606341],\n",
       "       [ 0.29068939,  0.01948267, -0.13231877],\n",
       "       [-0.00990838, -1.43037988, -1.39150685],\n",
       "       [-0.81415818, -0.52993076,  0.64765831],\n",
       "       [-1.15989473, -0.92940334,  1.79905975],\n",
       "       [-0.47764695,  0.55042856, -1.09133721],\n",
       "       [-0.79625338,  0.59382295, -0.8175826 ],\n",
       "       [ 0.12382737, -0.11773833,  0.04171723]])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.19567114,  0.45262704,  0.8391019 ,  0.15198421,  0.1275036 ,\n",
       "        -0.66307111, -1.32598806,  0.4092671 ,  0.21179886, -0.0075524 ],\n",
       "       [-0.16420053,  0.37982914,  0.70414563,  0.12753995,  0.10699666,\n",
       "        -0.55642661, -1.11272385,  0.34344296,  0.17773436, -0.00633771],\n",
       "       [ 0.22429458, -0.51883885, -0.96184855, -0.17421697, -0.14615526,\n",
       "         0.76006739,  1.51995806, -0.46913607, -0.24278151,  0.00865719]])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "XF = np.outer(pca.components_[0,:].T, F_1)\n",
    "XF"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "resid = X.T - XF"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.44051464,  0.81853216,  0.48824026,  0.13870518, -0.13741198,\n",
       "        -0.15108707,  0.16609333, -0.88691406, -1.00805224,  0.13137976],\n",
       "       [ 0.50883659, -0.13108215,  0.54618946, -0.10805728, -1.53737655,\n",
       "         0.02649585,  0.1833205 ,  0.2069856 ,  0.41608859, -0.11140062],\n",
       "       [ 0.75680494,  0.61811287,  0.82578515,  0.0418982 , -1.2453516 ,\n",
       "        -0.11240908,  0.27910169, -0.62220113, -0.57480108,  0.03306004]])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "resid"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 3.01100859, -0.01141558,  2.61840057],\n",
       "       [-0.01141558,  3.21231445,  2.34169749],\n",
       "       [ 2.61840057,  2.34169749,  3.99855146]])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(resid, resid.T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.decomposition import PCA\n",
    "\n",
    "class RiskModelPCA():\n",
    "    \n",
    "    ANN_FACTOR = 252\n",
    "    \n",
    "    def __init__(self, num_factors):\n",
    "        self._num_factors = num_factors\n",
    "        self.num_stocks_ = None\n",
    "        self.factor_betas_ = None\n",
    "        self.factor_returns_ = None\n",
    "        self.common_returns_ = None\n",
    "        self.residuals_ = None\n",
    "        self.factor_cov_matrix_ = None\n",
    "        self.idio_var_matrix_ = None\n",
    "        self.explained_variance_ratio_ = None\n",
    "\n",
    "    def fit(self, returns):\n",
    "        self.num_stocks_ = len(returns.columns)\n",
    "        mod = PCA(n_components=self._num_factors, svd_solver='full')\n",
    "        mod.fit(returns)\n",
    "        \n",
    "        self.factor_betas_ = pd.DataFrame(\n",
    "            data=mod.components_.T,\n",
    "            index=returns.columns\n",
    "        )\n",
    "        \n",
    "        self.factor_returns_ = pd.DataFrame(\n",
    "            data=mod.transform(returns),\n",
    "            index=returns.index\n",
    "        )\n",
    "        \n",
    "        self.explained_variance_ratio_ = mod.explained_variance_ratio_\n",
    "        \n",
    "        self.common_returns_ = pd.DataFrame(\n",
    "            data=np.dot(self.factor_returns_, self.factor_betas_.T),\n",
    "            index=returns.index\n",
    "        )\n",
    "        self.common_returns_.columns = returns.columns\n",
    "        \n",
    "        self.residuals_ = (returns - self.common_returns_)\n",
    "        \n",
    "        self.factor_cov_matrix_ = np.diag(\n",
    "            self.factor_returns_.var(axis=0, ddof=1)*RiskModelPCA.ANN_FACTOR\n",
    "        )\n",
    "        \n",
    "        self.idio_var_matrix_ = pd.DataFrame(\n",
    "            data=np.diag(np.var(self.residuals_))*RiskModelPCA.ANN_FACTOR,\n",
    "            index=returns.columns\n",
    "        )\n",
    "        \n",
    "        self.idio_var_vector_ = pd.DataFrame(\n",
    "            data=np.diag(self.idio_var_matrix_.values),\n",
    "            index=returns.columns\n",
    "        )\n",
    "        \n",
    "        self.idio_var_matrix_.columns = index=returns.columns\n",
    "\n",
    "    def get_factor_exposures(self, weights):\n",
    "        F = self.factor_betas_.loc[weights.index]\n",
    "        return F.T.dot(weights)\n",
    "\n",
    "    def predict(self, weights):\n",
    "        \"\"\" Calculates expected portfolio risk as sqrt(h'XFX'h + h'Sh).\n",
    "            This will fail if your portfolio has asset weights not in the risk model\"\"\"\n",
    "        all_assets = pd.DataFrame(\n",
    "            data=np.repeat(0, self.num_stocks_),\n",
    "            index=self.factor_betas_.index)\n",
    "        all_assets.loc[weights.index] = weights\n",
    "        \n",
    "            \n",
    "        h = all_assets\n",
    "        X = self.factor_betas_\n",
    "        F = self.factor_cov_matrix_\n",
    "        S = self.idio_var_matrix_\n",
    "        \n",
    "        return np.sqrt(h.T.dot(X).dot(F).dot(X.T).dot(h) + h.T.dot(S).dot(h))[0].values[0]\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "rm = RiskModelPCA(1)\n",
    "rm.fit(pd.DataFrame(X))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.301101</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.321231</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.399855</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          0         1         2\n",
       "0  0.301101  0.000000  0.000000\n",
       "1  0.000000  0.321231  0.000000\n",
       "2  0.000000  0.000000  0.399855"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rm.idio_var_matrix_/252"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
